package cn.parllay.dingdangproject.service.handler;


import cn.parllay.dingdangproject.entity.AskMsg;
import cn.parllay.dingdangproject.entity.BaseMsg;
import cn.parllay.dingdangproject.entity.LoginMsg;
import cn.parllay.dingdangproject.entity.LoginReplyMsg;
import cn.parllay.dingdangproject.entity.MsgType;
import cn.parllay.dingdangproject.entity.PingMsg;
import cn.parllay.dingdangproject.entity.ReplyClientBody;
import cn.parllay.dingdangproject.entity.ReplyMsg;
import cn.parllay.dingdangproject.entity.ReplyServerBody;
import cn.parllay.dingdangproject.service.NettyChannelMap;
import cn.parllay.dingdangproject.util.Utils_js;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;

public class NettyServerHandler extends SimpleChannelInboundHandler<Object> {

	//检测心跳
	@SuppressWarnings("static-access")
	@Override  
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
	   if (evt instanceof IdleStateEvent) {
           IdleStateEvent e = (IdleStateEvent) evt;
           switch (e.state()) {
           	   //写空闲   长期未向服务器发送数据 发送心跳
               /*case WRITER_IDLE:
                   PingMsg pingMsg=new PingMsg();
                   ctx.writeAndFlush(pingMsg);
                   //System.out.println("send ping to client--------");
                   break;*/
               //长期未收到客户端心跳数据
               case READER_IDLE:
            	   //未发送ping
            	   NettyChannelMap.remove((SocketChannel)ctx.channel());
                   ctx.channel().close();
                   System.out.println("READER_IDLE client no-ping too long time--------"
                		   +" "+new Utils_js().getNowTimeStrSSS());
                   break;
               case ALL_IDLE:
            	   NettyChannelMap.remove((SocketChannel)ctx.channel());
                   ctx.channel().close();
                   System.out.println("ALL_IDLE send to client--------"
                		   +" "+new Utils_js().getNowTimeStrSSS());
                   break;
               default:
                   break;
           }
       }
	} 
	
	//异常处理类
	@SuppressWarnings("static-access")
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		//NettyChannelMap.remove((SocketChannel)ctx.channel());
		ctx.channel().close();
		System.out.println("ServerHandler error--"+cause.getMessage()
		+" "+new Utils_js().getNowTimeStrSSS());
	}
	
    @SuppressWarnings("static-access")
	@Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        //channel失效，从Map中移除
        NettyChannelMap.remove((SocketChannel)ctx.channel());
        System.out.println("Channel Invalid -- "+new Utils_js().getNowTimeStrSSS());
    }
    
    @SuppressWarnings("static-access")
	@Override
    protected void messageReceived(ChannelHandlerContext channelHandlerContext, Object obj) throws Exception {
    	BaseMsg baseMsg=(BaseMsg)obj;
    	//判断不是LOGIN状态下  登录信息是否正确
        if(!MsgType.LOGIN.equals(baseMsg.getType()) && !MsgType.PING.equals(baseMsg.getType())
        		&& !MsgType.LOGOUT.equals(baseMsg.getType())){
        	String clientId = baseMsg.getClientId();
        	if(clientId == null){
        		//说明未登录，或者连接断了，服务器向客户端发起登录请求，让客户端重新登录
                LoginMsg loginMsg=new LoginMsg();
                channelHandlerContext.channel().writeAndFlush(loginMsg);
        		return ;
        	}
        	Channel channel = NettyChannelMap.get(clientId);
            if(channel==null){
                //说明未登录，或者连接断了，服务器向客户端发起登录请求，让客户端重新登录
                LoginMsg loginMsg=new LoginMsg();
                channelHandlerContext.channel().writeAndFlush(loginMsg);
                return;
            }
            
            Channel currentChannel = channelHandlerContext.channel();
            if(currentChannel != channel){
            	//登陆id不匹配
                LoginMsg loginMsg=new LoginMsg();
                channelHandlerContext.channel().writeAndFlush(loginMsg);
                return;
            }
            
        }
        switch (baseMsg.getType()){
	        case LOGIN:{
	            LoginMsg loginMsg=(LoginMsg)baseMsg;
	            Channel ch=NettyChannelMap.get(loginMsg.getUserName());
	            if(null == ch) {
	            	NettyChannelMap.add(loginMsg.getUserName(),(SocketChannel)channelHandlerContext.channel());
	                System.out.println("client="+loginMsg.getUserName()+" login success"
	                		+" "+new Utils_js().getNowTimeStrSSS());
	                LoginReplyMsg loginReplyMsg = new LoginReplyMsg();
	                loginReplyMsg.setSuccese(true);
	                loginReplyMsg.setLoginToken(loginMsg.getUserName());
	                channelHandlerContext.channel().writeAndFlush(loginReplyMsg);
	            }else {
	            	System.out.println("client="+loginMsg.getUserName()+" update success"
	            			+" "+new Utils_js().getNowTimeStrSSS());
		           	LoginReplyMsg loginReplyMsg = new LoginReplyMsg();
		           	loginReplyMsg.setSuccese(false);
	                channelHandlerContext.channel().writeAndFlush(loginReplyMsg);
	            }
	        }break;
            case PING:{
            	//收到客户端的ping 并返回ping
                //PingMsg pingMsg=(PingMsg)baseMsg;
                //PingMsg replyPing=new PingMsg();
                System.out.println("receive client ping:keepalive clientId="+baseMsg.getClientId()
                					+" "+new Utils_js().getNowTimeStrSSS());
                System.out.println("NettyChannelMap.getSize()= "+NettyChannelMap.getSize());
                //NettyChannelMap.get(pingMsg.getClientId()).writeAndFlush(replyPing);
            }break;
            case ASK:{
                //收到客户端的请求
                AskMsg askMsg=(AskMsg)baseMsg;
                //判断token  并回复客户端
                if("authToken".equals(askMsg.getParams().getAuth())){
                	//回复客户端
                    ReplyServerBody replyBody=new ReplyServerBody("server info--clientId="+baseMsg.getClientId()
                    		+" "+new Utils_js().getNowTimeStrSSS());
                    ReplyMsg replyMsg=new ReplyMsg();
                    replyMsg.setBody(replyBody);
                    NettyChannelMap.get(askMsg.getClientId()).writeAndFlush(replyMsg);
                }
            }break;
            case REPLY:{
                //收到客户端回复
                ReplyMsg replyMsg=(ReplyMsg)baseMsg;
                ReplyClientBody clientBody=(ReplyClientBody)replyMsg.getBody();
                System.out.println("receive client msg: "+clientBody.getClientInfo()
                		+" "+new Utils_js().getNowTimeStrSSS());
            }break;
            case LOGOUT:{
            	//NettyChannelMap删除通道
            	System.out.println("receive client-loginout msg----------------clientId="+baseMsg.getClientId()
        		+" "+new Utils_js().getNowTimeStrSSS());
            	NettyChannelMap.removeClientId(baseMsg.getClientId());
            	//NettyChannelMap.remove((SocketChannel)channelHandlerContext.channel());
            }break;
            
            default:{
            	System.out.println("receive client msg----------------"+obj.toString()
            		+" "+new Utils_js().getNowTimeStrSSS());
            };
        }
        ReferenceCountUtil.release(baseMsg);
    }
    
    
}
